/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package arbre;

/**
 *
 * @author Xuan Huy
 */
public class Noeud implements Cloneable {

    private int cle;
    private Noeud gauche = null;
    private Noeud droite = null;
    private Noeud parent = null;
    private Couleur couleur = Couleur.SANS_COULEUR;

    /**
     * Le constructeur par défaut construit un noeud sans initialiser les
     * attributs.
     */
    public Noeud() {
    }

    /**
     * Le constructeur construit un noeud en initialisant sa clé.
     *
     * @param cle la valeur de la clé du noeud nouvellement construit.
     */
    public Noeud(int cle) {
        this.cle = cle;
    }

    /**
     * Le constructeur construit un noeud en initialisant sa clé et sa couleur.
     *
     * @param cle la valeur de la clé du noeud nouvellement construit.
     * @param couleur la couleur du noeud nouvellement construit.
     */
    public Noeud(int cle, Couleur couleur) {
        this(cle);
        this.couleur = couleur;
    }

    /**
     * Le constructeur construit un noeud en initialisant sa clé, ses enfants
     * gauche et droite et son noeud parent dans un arbre binaire de recherche.
     *
     * @param cle la valeur de la clé du noeud nouvellement construit.
     * @param gauche l'enfant gauche.
     * @param droite l'enfant droite.
     * @param parent le noeud parent.
     * @see ArbreRecherche.
     */
    public Noeud(int cle, Noeud gauche, Noeud droite, Noeud parent) {
        this.cle = cle;
        this.gauche = gauche;
        this.droite = droite;
        this.parent = parent;
    }

    /**
     * Le constructeur construit un noeud en initialisant sa clé, ses enfants
     * gauche et droite, son noeud parent et sa couleur dans un arbre binaire de
     * recherche.
     *
     * @param cle la valeur de la clé du noeud nouvellement construit.
     * @param gauche l'enfant gauche.
     * @param droite l'enfant droite.
     * @param parent le noeud parent.
     * @param couleur la couleur.
     */
    public Noeud(int cle, Noeud gauche, Noeud droite, Noeud parent,
            Couleur couleur) {
        this(cle, gauche, droite, parent);
        this.couleur = couleur;
    }

    /**
     * La méthode retourne la valeur de la clé du noeud.
     *
     * @return la valeur de la clé du noeud.
     */
    public int getCle() {
        return cle;
    }

    /**
     * La méthode affecte la nouvelle valeur de la clé en écrasant l'ancienne.
     *
     * @param cle la nouvelle clé.
     */
    public void setCle(int cle) {
        this.cle = cle;
    }

    /**
     * La méthode retourne la couleur actuelle du noeud.
     *
     * @return la couleur du noeud.
     * @see Couleur.
     */
    public Couleur getCouleur() {
        return couleur;
    }

    /**
     * La méthode change la couleur du noeud en écrasant l'ancienne.
     *
     * @param couleur la nouvelle couleur.
     */
    public void setCouleur(Couleur couleur) {
        this.couleur = couleur;
    }

    /**
     * La méthode retourne la hauteur du noeud, si ce noeud fait partie d'un
     * arbre.
     *
     * @return la hauteur du noeud, ou <code>-1</code> si le noeud n'est pas
     * dans un arbre.
     */
    public int getHauteur() {
        if (parent == null && gauche == null && droite == null) {
            return -1;
        }
        int hauteurGauche = 0;
        int hauteurDroite = 0;
        if (gauche != null) {
            hauteurGauche = gauche.getHauteur() + 1;
        }
        if (droite != null) {
            hauteurDroite = droite.getHauteur() + 1;
        }
        if (hauteurGauche == 0) {
            return hauteurDroite;
        }
        if (hauteurDroite == 0) {
            return hauteurGauche;
        }
        if (hauteurGauche < hauteurDroite) {
            return hauteurGauche;
        }
        return hauteurDroite;
    }

    /**
     * La méthode retourne l'enfant gauche du noeud.
     *
     * @return l'enfant gauche du noeud, ou <code>null</code> si le noeud n'a
     * pas d'enfant gauche.
     */
    public Noeud getGauche() {
        return gauche;
    }

    /**
     * La méthode modifie l'enfant gauche du noeud actuel en écrasant l'ancient.
     *
     * @param gauche le nouvel enfant gauche.
     */
    public void setGauche(Noeud gauche) {
        this.gauche = gauche;
    }

    /**
     * La méthode retourne l'enfant droite du noeud.
     *
     * @return l'enfant droite du noeud, ou <code>null</code> si le noeud n'a
     * pas d'enfant droite.
     */
    public Noeud getDroite() {
        return droite;
    }

    /**
     * La méthode modifie l'enfant droite du noeud actuel en écrasant l'ancient.
     *
     * @param droite le nouvel enfant droite.
     */
    public void setDroite(Noeud droite) {
        this.droite = droite;
    }

    /**
     * La méthode retourne le noeud parent du noeud actuel.
     *
     * @return le noeud parent, ou <code>null</code> si le noeud n'a pas de
     * parent.
     */
    public Noeud getParent() {
        return parent;
    }

    /**
     * La méthode modifie le noeud parent du noeud actuel en écrasant l'ancien.
     *
     * @param parent le nouveau noeud parent.
     */
    public void setParent(Noeud parent) {
        this.parent = parent;
    }

    /**
     * La méthode détermine si ce noeud est la feuille d'un arbre binaire de
     * recherche.
     *
     * @return <code>true</code> si c'est une feuille, <code>false</code> sinon.
     */
    public boolean isFeuille() {
        return droite == null && gauche == null;
    }

    /**
     * La méthode retourne une copie de l'arbre enraciné par ce noeud. La
     * méthode copie également ses noeuds descendants s'il y en a, mais pas son
     * noeud parent. Le champs parent du noeud retourné vaudra
     * <code>null</code>.
     *
     * @return une copie de ce noeud.
     */
    @Override
    protected Object clone() {
        Noeud copy = null;
        try {
            copy = (Noeud) super.clone();
            if (gauche != null) {
                copy.gauche = (Noeud) gauche.clone();
                copy.gauche.parent = copy;
            }
            if (droite != null) {
                copy.droite = (Noeud) droite.clone();
                copy.droite.parent = copy;
            }
        } catch (CloneNotSupportedException ex) {
            ex.printStackTrace();
        }
        return copy;
    }
}
